package com.zuipin.util;

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * @ClassName: ArithUtil
 * @author wuyicheng
 * @time 2017年3月24日上午11:52:29
 */
public class ArithUtil {
	// 默认运算精度
	public static int DEF_SCALE = 2;
	
	private ArithUtil() {
		
	}
	
	/**
	 * 提供精确的加法运算。
	 * 
	 * @Title: add
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午12:37:30
	 * @param b1
	 *            被加数
	 * @param b2
	 *            加数
	 * @return 两个参数的和
	 * @return: BigDecimal
	 * @throws
	 */
	public static BigDecimal add(BigDecimal b1, BigDecimal b2) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		b2 = b2 == null ? new BigDecimal(0.00) : b2;
		return roundHalfUp(b1.add(b2), DEF_SCALE);
	}
	
	//	
	//	public static void main(String[] args) {
	//		BigDecimal b1 = new BigDecimal(0);
	//		BigDecimal b2 = new BigDecimal(0.00);
	//		BigDecimal b3 = null;
	//		System.out.println("+");
	//		System.out.println(add(b3, b1));
	//		System.out.println(add(b3, b1, 4));
	//		System.out.println("-");
	//		System.out.println(sub(b3, b1));
	//		System.out.println(sub(b3, b1, 4));
	//		System.out.println("*");
	//		System.out.println(mul(b3, b1));
	//		System.out.println(mul(b3, b1, 4));
	//		System.out.println("/");
	//		System.out.println(div(b1, b3));
	//		System.out.println(div(b1, b3, 4));
	//		System.out.println(compareTo(b1, b2));
	//		System.out.println(returnMax(b1, b2));
	//		System.out.println(returnMin(b1, b2));
	//		
	//		System.out.println(compareTo(b1, b3));
	//		System.out.println(returnMax(b1, b3));
	//		System.out.println(returnMin(b1, b3));
	//		
	//		System.out.println(getDecimals(b3));
	//		System.out.println(getDecimals(0.00f));
	//	}
	//	
	/**
	 * @Title: add
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午12:38:40
	 * @param b1
	 *            被加数
	 * @param b2
	 *            加数
	 * @param scle
	 *            保留几位小数
	 * @return 两个参数的和
	 * @return: BigDecimal
	 * @throws
	 */
	public static BigDecimal add(BigDecimal b1, BigDecimal b2, int scle) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		b2 = b2 == null ? new BigDecimal(0.00) : b2;
		return roundHalfUp(b1.add(b2), scle);
	}
	
	/**
	 * 提供精确的减法运算。
	 * 
	 * @Title: sub
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午1:38:49
	 * @param b1
	 *            被减数
	 * @param b2
	 *            减数
	 * @return 返回两个数差
	 * @return: BigDecimal
	 * @throws
	 */
	public static BigDecimal sub(BigDecimal b1, BigDecimal b2) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		b2 = b2 == null ? new BigDecimal(0.00) : b2;
		return roundHalfUp(b1.subtract(b2), DEF_SCALE);
	}
	
	/**
	 * 提供精确的减法运算。
	 * 
	 * @Title: sub
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午1:37:25
	 * @param v1
	 *            被减数
	 * @param v2
	 *            减数
	 * @param scle
	 *            保留几位小数
	 * @return 两个参数的差
	 * @return: double
	 * @throws
	 */
	public static BigDecimal sub(BigDecimal b1, BigDecimal b2, int scle) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		b2 = b2 == null ? new BigDecimal(0.00) : b2;
		return roundHalfUp(b1.subtract(b2), scle);
	}
	
	/**
	 * 两个参数的积
	 * 
	 * @Title: mul
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午1:41:10
	 * @param v1
	 *            被乘数
	 * @param v2
	 *            乘数
	 * @param scle
	 * @return 两个参数的积
	 * @return: double
	 * @throws
	 */
	public static BigDecimal mul(BigDecimal b1, BigDecimal b2, int scle) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		b2 = b2 == null ? new BigDecimal(0.00) : b2;
		return roundHalfUp(b1.multiply(b2), scle);
	}
	
	/**
	 * 两个参数的积
	 * 
	 * @Title: mul
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午1:41:10
	 * @param v1
	 *            被乘数
	 * @param v2
	 *            乘数
	 * @return 两个参数的积
	 * @return: double
	 * @throws
	 */
	public static BigDecimal mul(BigDecimal b1, BigDecimal b2) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		b2 = b2 == null ? new BigDecimal(0.00) : b2;
		return roundHalfUp(b1.multiply(b2), DEF_SCALE);
	}
	
	/**
	 * @throws Exception 
	 * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到 小数点以后10位，以后的数字四舍五入。
	 * 
	 * @Title: div
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午1:55:40
	 * @param b1
	 *            被除数
	 * @param b2
	 *            除数
	 * @return 两个参数的商
	 * @return: BigDecimal
	 * @throws
	 */
	public static BigDecimal div(BigDecimal b1, BigDecimal b2) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		if (b2 == null || b2.compareTo(new BigDecimal(0.00)) == 0) {
			throw new IllegalArgumentException("除数不能为零");
		}
		return b1.divide(b2, DEF_SCALE, BigDecimal.ROUND_HALF_UP);
	}
	
	/**
	 * @throws Exception 
	 * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到 小数点以后10位，以后的数字四舍五入。
	 * 
	 * @Title: div
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午1:55:45
	 * @param b1
	 *            被除数
	 * @param b2
	 *            除数
	 * @param scale
	 *            保留小数位
	 * @return两个参数的商
	 * @return: BigDecimal
	 * @throws
	 */
	public static BigDecimal div(BigDecimal b1, BigDecimal b2, int scale) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		if (b2 == null || b2.compareTo(new BigDecimal(0.00)) == 0) {
			throw new IllegalArgumentException("除数不能为零");
		}
		if (scale < 0) {
			throw new IllegalArgumentException("参数scale必须为零或正整数!");
		}
		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
	}
	
	/**
	 * 提供精确的小数位四舍五入处理。
	 * 
	 * @Title: roundHalfUp
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午12:31:02
	 * @param bigDecimal
	 *            需要四舍五入的数字
	 * @param scale
	 *            小数点后保留几位
	 * @return
	 * @return: BigDecimal 四舍五入后的结果
	 * @throws
	 */
	public static BigDecimal roundHalfUp(BigDecimal bigDecimal, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("参数scale必须为整数为零!");
		}
		return bigDecimal.setScale(scale, BigDecimal.ROUND_HALF_UP);
	}
	
	/**
	 * 舍去小数
	 * 
	 * @Title: roundDown
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午12:33:49
	 * @param bigDecimal
	 * @param scale
	 *            小数点后保留几位
	 * @return
	 * @return: BigDecimal
	 * @throws
	 */
	public static BigDecimal roundDown(BigDecimal bigDecimal, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("参数scale必须为整数为零!");
		}
		return bigDecimal.setScale(scale, BigDecimal.ROUND_DOWN);
	}
	
	/**
	 * 返回大的那个数
	 * 
	 * @Title: returnMax
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午2:10:04
	 * @param b1
	 *            需要被对比的第一个数
	 * @param b2
	 *            需要被对比的第二个数
	 * @return
	 * @return: BigDecimal
	 * @throws
	 */
	public static BigDecimal returnMax(BigDecimal b1, BigDecimal b2) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		b2 = b2 == null ? new BigDecimal(0.00) : b2;
		return b1.max(b2);
	}
	
	/**
	 * @param v1
	 *            需要被对比的第一个数
	 * @param v2
	 * @return
	 */
	/**
	 * 返回两个数中小的一个值
	 * 
	 * @Title: returnMin
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午2:11:59
	 * @param b1
	 *            需要被对比的第一个数
	 * @param b2
	 *            需要被对比的第二个数需要被对比的第二个数
	 * @return 返回两个数中小的一个值
	 * @return: BigDecimal
	 * @throws
	 */
	public static BigDecimal returnMin(BigDecimal b1, BigDecimal b2) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		b2 = b2 == null ? new BigDecimal(0.00) : b2;
		return b1.min(b2);
	}
	
	/**
	 * 精确比较两个数字
	 * 
	 * @Title: compareTo
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午2:13:22
	 * @param b1
	 *            需要被对比的第一个数
	 * @param b2
	 *            需要被对比的第二个数
	 * @return
	 * @return: int 如果两个数一样则返回0，如果第一个数比第二个数大则返回1，反之返回-1
	 * @throws
	 */
	public static int compareTo(BigDecimal b1, BigDecimal b2) {
		b1 = b1 == null ? new BigDecimal(0.00) : b1;
		b2 = b2 == null ? new BigDecimal(0.00) : b2;
		return b1.compareTo(b2);
	}
	
	/**
	 * 获取数字小数位数
	 * 
	 * @param number
	 *            数字.
	 * @return 小数位数
	 */
	public static int getDecimals(BigDecimal bigDecimal) {
		if (bigDecimal == null) {
			return 0;
		}
		DecimalFormat decimalFormat = new DecimalFormat("#.####");
		String numberString = decimalFormat.format(bigDecimal);
		if (numberString.indexOf(".") > 0) {
			return numberString.length() - String.valueOf(bigDecimal).indexOf(".") - 1;
		} else {
			return 0;
		}
	}
	
	/**
	 * 获取数字小数位数
	 * 
	 * @param number
	 *            数字
	 * @return 小数位数
	 */
	public static int getDecimals(float number) {
		DecimalFormat decimalFormat = new DecimalFormat("#.####");
		String numberString = decimalFormat.format(number);
		if (numberString.indexOf(".") > 0) {
			return numberString.length() - String.valueOf(number).indexOf(".") - 1;
		} else {
			return 0;
		}
	}
	
	/**
	 * 格式化数字保留两位小数
	 * 
	 * @Title: formatNumber
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午2:26:45
	 * @param bigDecimal
	 * @return
	 * @return: String
	 * @throws
	 */
	public static String formatNumber(BigDecimal bigDecimal) {
		DecimalFormat fmt = new DecimalFormat("#0.00");
		if (bigDecimal == null) {
			bigDecimal = new BigDecimal(0);
		}
		return fmt.format(bigDecimal);
		
	}
	
	/**
	 * 格式化数字
	 * 
	 * @Title: formatNumber
	 * @author: wuyicheng
	 * @date: 2017年3月24日下午2:27:09
	 * @param bigDecimal
	 * @param format
	 *            格式
	 * @return
	 * @return: String
	 * @throws
	 */
	public static String formatNumber(BigDecimal bigDecimal, String format) {
		DecimalFormat fmt = new DecimalFormat(format);
		if (bigDecimal == null) {
			bigDecimal = new BigDecimal(0);
		}
		return fmt.format(bigDecimal);
	}
	
	public static void main(String[] args) {
		System.out.println(ArithUtil.div(new BigDecimal(1), new BigDecimal(100)));
	}
}
